#include "button_drv.h"
#include "modbus_user.h"
#include "beep_drv.h"

BtnInfo_t BtnHandle_Map[2][3] = 
{
    {
        {1, BTN_STATE_RELEASE, 0, 0, TRUE, 0, NULL},
        {2, BTN_STATE_RELEASE, 0, 0, TRUE, 0, NULL},
        {3, BTN_STATE_RELEASE, 0, 0, TRUE, 0, NULL},
    },
    {
        {4, BTN_STATE_RELEASE, 0, 0, TRUE, 0, NULL},
        {5, BTN_STATE_RELEASE, 0, 0, TRUE, 0, NULL},
        {6, BTN_STATE_RELEASE, 0, 0, TRUE, 0, NULL},
    }
};

BtnPin_t RowPin[BTN_ROW_CNT] = 
{
    {3, 4},
    {3, 5},
};
BtnPin_t ColPin[BTN_COL_CNT] = 
{
    {3, 3},
    {3, 6},
    {3, 7},
};

void Button_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.Pin = GPIO_Pin_3 | GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStruct.Mode = GPIO_PullUp;
    GPIO_Inilize(GPIO_P3, &GPIO_InitStruct);

    GPIO_InitStruct.Pin =  GPIO_Pin_4 | GPIO_Pin_5;
    GPIO_InitStruct.Mode = GPIO_OUT_PP;
    GPIO_Inilize(GPIO_P3, &GPIO_InitStruct);
    P34 = 1;
    P35 = 1;
}

void Beep()
{
    uint32_t currTick = 0;
    static uint32_t lastTick  = 0;
    currTick = GetTick();
    BEEP_OFF();
    if(currTick - lastTick <= 2000)  return;
    
        lastTick = currTick;
        BEEP_ON();                 
    
}

void Button_Scan(void)
{
    static size_t  row = 0;
    static size_t  col = 0; 
    bit level = 0;
    uint32_t currTick = 0;

    for (; row < BTN_ROW_CNT; row++)
    {
        Set_Pin(RowPin[row].port, RowPin[row].pin, 0);
        for (; col < BTN_COL_CNT; col++)
        {                
            switch (BtnHandle_Map[row][col].State)
            {
            case BTN_STATE_RELEASE:
                level = Read_Pin(ColPin[col].port, ColPin[col].pin);
                if(level == 0)
                    // 通过按键扫描任务的20ms间隔作为消抖时间
                    BtnHandle_Map[row][col].State = BTN_STATE_CONFIRM;
                break;
            case BTN_STATE_CONFIRM:                
                level = Read_Pin(ColPin[col].port, ColPin[col].pin);
                if(level == 0)
                {
                    BtnHandle_Map[row][col].State = BTN_STATE_PRESS;
                    return;
                }
                break;
            case BTN_STATE_PRESS:
                currTick = GetTick();

                MB_00.Button = BtnHandle_Map[row][col].btnLabel;
                                  
                level = Read_Pin(ColPin[col].port, ColPin[col].pin);
                if(level != 0)
                {
                    BtnHandle_Map[row][col].State = BTN_STATE_RELEASE;
                    BtnHandle_Map[row][col].pressOnce = TRUE;
                    MB_00.Button = 0;
                    BEEP_OFF();   
                    return;
                }  

                if(currTick - BtnHandle_Map[row][col].longTime > 1000 && !BtnHandle_Map[row][col].pressOnce)                  
                    BtnHandle_Map[row][col].State = BTN_STATE_LONG;  
                               
                if(!BtnHandle_Map[row][col].pressOnce)  break;       
                
                BtnHandle_Map[row][col].longTime = currTick;              
                BtnHandle_Map[row][col].pressOnce = FALSE;     

                if(BtnHandle_Map[row][col].BtnCallback != NULL) 
                    BtnHandle_Map[row][col].BtnCallback();
                    
                break;
            case BTN_STATE_LONG:
                    currTick = GetTick();   
                    BEEP_OFF();    
                    // 长按状态每600ms调用一次回调函数
                    if(currTick - BtnHandle_Map[row][col].lastTime < 600) break;
                    BtnHandle_Map[row][col].lastTime = currTick;
                    BEEP_ON();
                    if(BtnHandle_Map[row][col].BtnLongCallback != NULL)
                    {
                        BtnHandle_Map[row][col].BtnLongCallback();
                    }
                    level = Read_Pin(ColPin[col].port, ColPin[col].pin);
                    if(level != 0)
                    {
                        BtnHandle_Map[row][col].State = BTN_STATE_RELEASE;
                        BtnHandle_Map[row][col].pressOnce = TRUE;
                        MB_00.Button = 0;
                        BEEP_OFF(); 
                        return;
                    }
                    break;
                default:   
                break;
            }
        }
        col = 0;
        Set_Pin(RowPin[row].port, RowPin[row].pin, 1);
    }
    row = 0;
}

BOOL BtnRegister(BtnLabel_t btnLabel, void (*BtnCallback)(void), BtnCbType_t cbType)
{   
    size_t i = 0 , j = 0;
    for(; i < BTN_ROW_CNT; i++)
    {
        for(j = 0; j < BTN_COL_CNT; j++)
        {
            if(BtnHandle_Map[i][j].btnLabel == btnLabel)
            {
                switch(cbType)
                {
                    case BTN_CB_FUNC:
                        BtnHandle_Map[i][j].BtnCallback = BtnCallback;
                        break;
                    case BTN_CB_LONG:
                        BtnHandle_Map[i][j].BtnLongCallback = BtnCallback;
                        break;
                    default:
                        break;
                }
                return TRUE;
            }
        }
    }
    return FALSE;
}

void Set_Pin(uint8_t port, uint8_t pin, bit level) 
{
    switch(port) 
    {
        case 0: level ? (P0 |= (1<<pin)) : (P0 &= ~(1<<pin)); break;
        case 1: level ? (P1 |= (1<<pin)) : (P1 &= ~(1<<pin)); break;
        case 2: level ? (P2 |= (1<<pin)) : (P2 &= ~(1<<pin)); break;
        case 3: level ? (P3 |= (1<<pin)) : (P3 &= ~(1<<pin)); break;
    }
}

BOOL Read_Pin(uint8_t port, uint8_t pin) 
{
    switch(port) 
    {
        case 0: return (P0 & (1<<pin));
        case 1: return (P1 & (1<<pin));
        case 2: return (P2 & (1<<pin));
        case 3: return (P3 & (1<<pin));
        default: return 0;
    }
}
